import detectEthereumProvider from '@metamask/detect-provider';
import { LoadingButton } from '@mui/lab';
import {
    Box,
    Button,
    Card,
    Checkbox,
    Dialog,
    DialogContent,
    DialogTitle,
    Divider,
    FormControlLabel,
    Grid,
    Typography
} from '@mui/material';
import React, { useCallback, useContext, useEffect, useState } from 'react';
import Web3 from 'web3';
import create from 'zustand';

import FeeManager from '../../../../api/fee/fee-manager';
import PaymentManager from '../../../../api/payment/payment-manager';
import Config from '../../../../config';
import { DisbursementFlow } from '../../../../constants/disbursement-flow';
import Routes from '../../../../constants/routes';
import { XLD_WALLET_ADDRESS } from '../../../../constants/wallet';
import NumberTool from '../../../../libs/number-tool';
import Web3Manager from '../../../../libs/web3-manager';
import Countdown from '../../countdown';
import { DialogContext } from '../dynamic-dialogs';
import { useStyles } from '../UIs/styled-mui-dialog';

type ConfirmDisburseStore = {
    open: boolean;
    close?: () => void;
    data?: any;
    onSubmit?: (flow: DisbursementFlow) => void;
};

const useConfirmStore = create<ConfirmDisburseStore>((set) => ({
    open: false,
    close: () => set({ open: false }),
    data: {},
    onSubmit: undefined
}));

export const confirmDisbursementDialog = ({ open, data, onSubmit }: ConfirmDisburseStore) => {
    useConfirmStore.setState({
        open,
        data,
        onSubmit
    });
};

export const ConfirmDisbursementDialog = () => {
    const { setValue } = useContext(DialogContext);
    const [isTimeout, setIsTimeout] = useState<boolean>(false);
    const [loading, setLoading] = useState<boolean>(false);
    const [confirmed, setConfirmed] = useState<boolean>(false);
    const [fee, setFee] = useState<number>(0);
    const [error, setError] = useState<string>('');
    const style = useStyles();
    const { open, close, data, onSubmit } = useConfirmStore();
    const { transactions = [], token = '', transactionFee = 0, network, abi, disbursement } = data;

    const getTotalAmount = (): number => {
        let amount = 0;
        if (transactions.length > 0) {
            for (let i = 0; i < transactions.length; i++) {
                if (!Number.isNaN(amount) && transactions[i].amount > 0) {
                    amount += transactions[i].amount;
                }
            }
        }

        return amount;
    };

    const getFee = (): number => {
        return token === 'SLP' ? transactionFee : fee;
    };

    const getTotalFee = (): number => {
        if (isSLP()) {
            return getFee() * transactions.length;
        } else {
            return fee;
        }
    };

    const getTokenIcon = () => {
        return Config.getAPI() + '/images/coins/' + token + '.png';
    };

    useEffect(() => {
        if (network) {
            setLoading(true);
            FeeManager.getEVM(token, network.id, transactions.length, disbursement.id)
                .then((evm) => {
                    setFee(Number(evm.amount));
                })
                .finally(() => setLoading(false));
        }
    }, [network]);

    const handleMetaMaskPay = async () => {
        const isMatch = await Web3Manager.isNetworkMatch(network);

        if (isMatch) {
            setLoading(true);
            setError('');
            try {
                const provider = await detectEthereumProvider();
                const address = await Web3Manager.getWalletAddress();
                const web3 = new Web3(provider as any);
                // eslint-disable-next-line new-cap
                const contract = new (web3 as any).eth.Contract(abi, network.address);

                const web3Manager = new Web3Manager();
                const totalAmount = await web3Manager.convertNumberToWei(
                    contract,
                    getTotalAmount() + getTotalFee()
                );

                await contract.methods
                    .transfer(XLD_WALLET_ADDRESS.get(Config.getEnvironment()), totalAmount)
                    .send({
                        from: address
                    })
                    .on('error', (err) => {
                        console.error(err);
                    })
                    .on('transactionHash', (hash) => {
                        if (hash) {
                            PaymentManager.setTransactionHash(
                                disbursement.id,
                                hash,
                                token,
                                network.id
                            ).then(() => {
                                onSubmit(DisbursementFlow.SUCCESS);
                                close();
                            });
                        }
                    });
            } catch (e) {
                setError(e.message);
            } finally {
                setLoading(false);
            }
        } else {
            setError('Your wallet does not match the network');
        }
    };

    const onClickPay = () => {
        if (isSLP()) {
            close();
            onSubmit(DisbursementFlow.PAY);
        } else {
            handleMetaMaskPay().then();
        }
    };

    const isSLP = () => {
        return token.toLowerCase() === 'slp' && network.id.toLowerCase() === 'ronin';
    };

    const onTimeout = useCallback(() => {
        setIsTimeout(true);
    }, []);

    useEffect(() => {
        open && isTimeout && setIsTimeout(false);
    }, [open]);

    return (
        <>
            <Dialog open={open} maxWidth="sm" fullWidth disableEscapeKeyDown={true}>
                <Box className={`${style.dialogBackground} ${style.center}`}>
                    <DialogTitle className={style.textTitle}>Confirm your Disbursement</DialogTitle>
                </Box>
                <DialogContent className={`${style.dialogBackground} ${style.center}`}>
                    <div className="p-2">
                        {!isTimeout && (
                            <Typography
                                variant="h6"
                                align={'center'}
                                color="white"
                                sx={{ pb: 1, marginTop: '-1rem', marginBottom: '1rem' }}
                            >
                                Price is locked. You have{' '}
                                <span style={{ color: 'var(--color-warning)' }}>
                                    <Countdown
                                        timer={900}
                                        onTimeout={onTimeout}
                                        syncTime={(time) => setValue({ time })}
                                    />{' '}
                                    minutes
                                </span>{' '}
                                to complete this transaction
                            </Typography>
                        )}
                        <Typography variant="h6" color="white" sx={{ pb: 1 }}>
                            Total amount to pay
                        </Typography>
                        <Card className={style.card}>
                            <Box display="flex" alignItems="center" justifyContent="center">
                                <Typography
                                    variant="body1"
                                    className={style.textContent}
                                    align="center"
                                >
                                    {token == 'SLP'
                                        ? NumberTool.format(
                                              NumberTool.roundUp(getTotalAmount() + getTotalFee()),
                                              token,
                                              2
                                          )
                                        : NumberTool.format(
                                              getTotalAmount() + getTotalFee(),
                                              token,
                                              2
                                          )}{' '}
                                    {token}
                                </Typography>
                                <Box
                                    component="img"
                                    className={style.bigIcon}
                                    alt="Icon"
                                    src={getTokenIcon()}
                                />
                            </Box>
                        </Card>

                        <Typography variant="h6" color="white" sx={{ pb: 1, mt: 3 }}>
                            Payment Details
                        </Typography>
                        <Card className={style.card}>
                            <Grid container spacing={2}>
                                <Grid item xs={6}>
                                    <Typography variant="h6" color="white">
                                        Amount
                                    </Typography>
                                </Grid>
                                <Grid item xs={6} textAlign="right">
                                    <Box
                                        display="flex"
                                        alignItems="center"
                                        justifyContent="flex-end"
                                    >
                                        <Typography variant="h6" color="white">
                                            {NumberTool.format(getTotalAmount())} {token}
                                        </Typography>
                                        <Box
                                            component="img"
                                            className={style.icon}
                                            alt="Icon"
                                            src={getTokenIcon()}
                                        />
                                    </Box>
                                </Grid>
                                <Grid item xs={6}>
                                    <Typography variant="h6" color="white">
                                        FEES
                                    </Typography>
                                </Grid>
                                <Grid item xs={6} textAlign="right">
                                    <Box
                                        display="flex"
                                        alignItems="center"
                                        justifyContent="flex-end"
                                    >
                                        <Typography variant="h6" color="white">
                                            {NumberTool.format(getTotalFee(), token, 2)} {token}
                                        </Typography>
                                        <Box
                                            component="img"
                                            className={style.icon}
                                            alt="Icon"
                                            src={getTokenIcon()}
                                        />
                                    </Box>
                                </Grid>
                                <Grid item xs={12}>
                                    <Divider sx={{ borderColor: '#ffffff' }} />
                                </Grid>
                                <Grid item xs={6}>
                                    <Typography variant="h6" color="white">
                                        TOTAL
                                    </Typography>
                                </Grid>
                                <Grid item xs={6} textAlign="right">
                                    <Box
                                        display="flex"
                                        alignItems="center"
                                        justifyContent="flex-end"
                                    >
                                        <Typography variant="h6" color="white">
                                            {NumberTool.format(
                                                getTotalAmount() + getTotalFee(),
                                                token,
                                                2
                                            )}{' '}
                                            {token}
                                        </Typography>
                                        <Box
                                            component="img"
                                            className={style.icon}
                                            alt="Icon"
                                            src={getTokenIcon()}
                                        />
                                    </Box>
                                </Grid>
                            </Grid>
                        </Card>
                        {isTimeout && (
                            <Typography
                                variant="h6"
                                align={'center'}
                                sx={{
                                    marginTop: '1rem',
                                    color: 'var(--color-warning-2)'
                                }}
                            >
                                Payment not received within the required window. Transactions won't
                                be sent. Please try to disburse again.
                            </Typography>
                        )}

                        {!isSLP() && (
                            <FormControlLabel
                                control={
                                    <Checkbox
                                        checked={confirmed}
                                        onChange={(e) => setConfirmed(e.target.checked)}
                                    />
                                }
                                label={
                                    <Typography variant="h6" color="white" sx={{ pb: 1, mt: 3 }}>
                                        I understand that XLD is not liable in the event that the
                                        supplied account details are incorrect
                                    </Typography>
                                }
                            />
                        )}

                        {error && (
                            <Typography
                                variant="h6"
                                align={'center'}
                                sx={{
                                    marginTop: '10',
                                    color: 'red'
                                }}
                            >
                                {error}
                            </Typography>
                        )}

                        <LoadingButton
                            variant="contained"
                            component="label"
                            onClick={() => {
                                onClickPay();
                            }}
                            className={`mt-4 w-100 ${style.button}`}
                            disabled={isTimeout || (isSLP() ? false : loading || !confirmed)}
                            loading={loading}
                        >
                            {isSLP() ? 'Pay with Ronin' : 'Pay with Metamask'}
                        </LoadingButton>
                        <Button
                            className={`${style.button} mt-4 ${!isTimeout && 'd-none'}`}
                            variant="contained"
                            href={Routes.HOME}
                            fullWidth
                        >
                            Exit Disbursement
                        </Button>
                    </div>
                </DialogContent>
            </Dialog>
        </>
    );
};
